/**
 * @file service_discovery.cpp
 * @brief API网关服务发现功能实现
 * @details 提供服务注册、发现、健康检查等功能的具体实现
 * 
 * @author 29108
 * @date 2025/7/25
 */

#include "core_services/api_gateway/service_discovery.h"
#include "common/logger/logger.h"
#include <algorithm>
#include <sstream>
#include <set>

namespace core_services {
namespace api_gateway {

    ServiceDiscovery::ServiceDiscovery(const Config& config, 
                                     std::shared_ptr<LoadBalancer> load_balancer)
        : config_(config), load_balancer_(load_balancer) {
        
        // 初始化HTTP客户端用于健康检查
        if (config_.enable_service_discovery) {
            http_client_ = std::make_unique<common::http::HttpClient>();
        }
        
        LOG_INFO("服务发现管理器初始化完成");
    }

    ServiceDiscovery::~ServiceDiscovery() {
        stop();
    }

    void ServiceDiscovery::start() {
        if (!config_.enable_service_discovery) {
            LOG_INFO("服务发现功能已禁用");
            return;
        }

        if (running_.load()) {
            LOG_WARNING("服务发现已在运行中");
            return;
        }

        running_.store(true);
        
        // 启动健康检查线程
        health_check_thread_ = std::make_unique<std::thread>(&ServiceDiscovery::healthCheckLoop, this);
        
        LOG_INFO("服务发现管理器启动成功");
    }

    void ServiceDiscovery::stop() {
        if (!running_.load()) {
            return;
        }

        running_.store(false);
        
        // 等待健康检查线程结束
        if (health_check_thread_ && health_check_thread_->joinable()) {
            health_check_thread_->join();
        }
        
        LOG_INFO("服务发现管理器已停止");
    }

    bool ServiceDiscovery::registerService(const ServiceInfo& service_info) {
        try {
            // 先在锁内完成服务注册
            {
                std::lock_guard<std::mutex> lock(services_mutex_);

                // 查找或创建服务列表
                auto& service_list = services_[service_info.service_name];

                // 检查是否已存在相同的服务实例
                auto instance_id = generateInstanceId(service_info.host, service_info.port);
                auto it = std::find_if(service_list.begin(), service_list.end(),
                    [&](const ServiceInfo& info) {
                        return generateInstanceId(info.host, info.port) == instance_id;
                    });

                if (it != service_list.end()) {
                    // 更新现有实例
                    *it = service_info;
                    it->last_heartbeat = std::chrono::system_clock::now();
                    LOG_INFO("更新服务实例: " + service_info.service_name +
                            " (" + service_info.host + ":" + std::to_string(service_info.port) + ")");
                } else {
                    // 添加新实例
                    ServiceInfo new_service = service_info;
                    new_service.last_heartbeat = std::chrono::system_clock::now();
                    service_list.push_back(new_service);
                    LOG_INFO("注册新服务实例: " + service_info.service_name +
                            " (" + service_info.host + ":" + std::to_string(service_info.port) + ")");
                }
            } // 锁在这里释放

            // 在锁外更新负载均衡器，避免死锁
            updateLoadBalancerInstances(service_info.service_name);

            return true;

        } catch (const std::exception& e) {
            LOG_ERROR("注册服务失败: " + std::string(e.what()));
            return false;
        }
    }

    bool ServiceDiscovery::deregisterService(const std::string& service_name,
                                           const std::string& host, int port) {
        try {
            bool found = false;

            // 先在锁内完成服务注销
            {
                std::lock_guard<std::mutex> lock(services_mutex_);

                auto service_it = services_.find(service_name);
                if (service_it == services_.end()) {
                    LOG_WARNING("尝试注销不存在的服务: " + service_name);
                    return false;
                }

                auto& service_list = service_it->second;
                auto instance_id = generateInstanceId(host, port);

                auto it = std::remove_if(service_list.begin(), service_list.end(),
                    [&](const ServiceInfo& info) {
                        return generateInstanceId(info.host, info.port) == instance_id;
                    });

                if (it != service_list.end()) {
                    service_list.erase(it, service_list.end());
                    LOG_INFO("注销服务实例: " + service_name + " (" + host + ":" + std::to_string(port) + ")");

                    // 如果服务列表为空，删除整个服务
                    if (service_list.empty()) {
                        services_.erase(service_it);
                        LOG_INFO("服务完全注销: " + service_name);
                    }

                    found = true;
                } else {
                    LOG_WARNING("未找到要注销的服务实例: " + service_name +
                               " (" + host + ":" + std::to_string(port) + ")");
                }
            } // 锁在这里释放

            // 在锁外更新负载均衡器
            if (found) {
                updateLoadBalancerInstances(service_name);
            }

            return found;

        } catch (const std::exception& e) {
            LOG_ERROR("注销服务失败: " + std::string(e.what()));
            return false;
        }
    }

    bool ServiceDiscovery::updateHeartbeat(const std::string& service_name, 
                                         const std::string& host, int port) {
        try {
            std::lock_guard<std::mutex> lock(services_mutex_);
            
            auto service_it = services_.find(service_name);
            if (service_it == services_.end()) {
                return false;
            }
            
            auto& service_list = service_it->second;
            auto instance_id = generateInstanceId(host, port);
            
            auto it = std::find_if(service_list.begin(), service_list.end(),
                [&](const ServiceInfo& info) {
                    return generateInstanceId(info.host, info.port) == instance_id;
                });
            
            if (it != service_list.end()) {
                it->last_heartbeat = std::chrono::system_clock::now();
                it->healthy = true;
                LOG_INFO("更新服务心跳: " + service_name + " (" + host + ":" + std::to_string(port) + ")");
                return true;
            }
            
            LOG_WARNING("心跳更新失败，服务实例不存在: " + service_name + " (" + host + ":" + std::to_string(port) + ")");
            return false;
            
        } catch (const std::exception& e) {
            LOG_ERROR("更新心跳失败: " + std::string(e.what()));
            return false;
        }
    }

    bool ServiceDiscovery::updateHeartbeatWithMetadata(const std::string& service_name, 
                                                      const std::string& host, int port,
                                                      const ServiceInfo& updated_info) {
        try {
            std::lock_guard<std::mutex> lock(services_mutex_);
            
            auto service_it = services_.find(service_name);
            if (service_it == services_.end()) {
                LOG_WARNING("心跳更新失败，服务不存在: " + service_name);
                return false;
            }
            
            auto& service_list = service_it->second;
            auto instance_id = generateInstanceId(host, port);
            
            auto it = std::find_if(service_list.begin(), service_list.end(),
                [&](const ServiceInfo& info) {
                    return generateInstanceId(info.host, info.port) == instance_id;
                });
            
            if (it != service_list.end()) {
                // 更新心跳时间和健康状态
                it->last_heartbeat = std::chrono::system_clock::now();
                it->healthy = updated_info.healthy;
                
                // 重要：更新metadata - 这是关键修复！
                if (!updated_info.metadata.empty()) {
                    it->metadata = updated_info.metadata;
                    LOG_DEBUG("更新服务metadata: " + service_name + ", 条目数: " + std::to_string(it->metadata.size()));
                    
                    // 记录关键metadata更新（用于调试）
                    if (it->metadata.find("current_players") != it->metadata.end()) {
                        LOG_DEBUG("  - current_players: " + it->metadata.at("current_players"));
                    }
                    if (it->metadata.find("load_percentage") != it->metadata.end()) {
                        LOG_DEBUG("  - load_percentage: " + it->metadata.at("load_percentage"));
                    }
                    if (it->metadata.find("server_status") != it->metadata.end()) {
                        LOG_DEBUG("  - server_status: " + it->metadata.at("server_status"));
                    }
                }
                
                LOG_INFO("更新服务心跳和metadata: " + service_name + " (" + host + ":" + std::to_string(port) + ")");
                return true;
            }
            
            LOG_WARNING("心跳更新失败，服务实例不存在: " + service_name + " (" + host + ":" + std::to_string(port) + ")");
            return false;
            
        } catch (const std::exception& e) {
            LOG_ERROR("更新心跳和metadata失败: " + std::string(e.what()));
            return false;
        }
    }

    std::vector<ServiceDiscovery::ServiceInfo> ServiceDiscovery::getServices(const std::string& service_name) const {
        std::lock_guard<std::mutex> lock(services_mutex_);
        
        auto it = services_.find(service_name);
        if (it != services_.end()) {
            return it->second;
        }
        
        return {};
    }

    std::vector<ServiceDiscovery::ServiceInfo> ServiceDiscovery::getHealthyServices(const std::string& service_name) const {
        std::lock_guard<std::mutex> lock(services_mutex_);
        return getHealthyServicesInternal(service_name);
    }

    std::vector<ServiceDiscovery::ServiceInfo> ServiceDiscovery::getHealthyServicesInternal(const std::string& service_name) const {
        auto it = services_.find(service_name);
        if (it == services_.end()) {
            return {};
        }

        std::vector<ServiceInfo> healthy_services;
        std::copy_if(it->second.begin(), it->second.end(),
                    std::back_inserter(healthy_services),
                    [](const ServiceInfo& info) { return info.healthy; });

        return healthy_services;
    }

    bool ServiceDiscovery::hasService(const std::string& service_name) const {
        std::lock_guard<std::mutex> lock(services_mutex_);
        return services_.find(service_name) != services_.end();
    }

    std::unordered_map<std::string, size_t> ServiceDiscovery::getServiceStats() const {
        std::lock_guard<std::mutex> lock(services_mutex_);
        
        std::unordered_map<std::string, size_t> stats;
        for (const auto& [service_name, service_list] : services_) {
            size_t healthy_count = std::count_if(service_list.begin(), service_list.end(),
                [](const ServiceInfo& info) { return info.healthy; });
            stats[service_name + "_total"] = service_list.size();
            stats[service_name + "_healthy"] = healthy_count;
        }
        
        return stats;
    }

    std::vector<ServiceDiscovery::ServiceInfo> ServiceDiscovery::getServicesByMetadata(
        const std::unordered_map<std::string, std::string>& metadata_filters,
        bool healthy_only) const {
        
        std::lock_guard<std::mutex> lock(services_mutex_);
        std::vector<ServiceInfo> result;
        
        for (const auto& [service_name, service_list] : services_) {
            for (const auto& service : service_list) {
                // 检查健康状态筛选
                if (healthy_only && !service.healthy) {
                    continue;
                }
                
                // 检查元数据筛选条件
                bool matches_all_filters = true;
                for (const auto& [key, value] : metadata_filters) {
                    auto it = service.metadata.find(key);
                    if (it == service.metadata.end() || it->second != value) {
                        matches_all_filters = false;
                        break;
                    }
                }
                
                if (matches_all_filters) {
                    result.push_back(service);
                }
            }
        }
        
        return result;
    }

    std::vector<ServiceDiscovery::ServiceInfo> ServiceDiscovery::getServicesByGameType(
        const std::string& game_type, bool healthy_only) const {
        
        std::unordered_map<std::string, std::string> game_type_filter = {
            {"game_type", game_type}
        };
        
        return getServicesByMetadata(game_type_filter, healthy_only);
    }

    std::vector<ServiceDiscovery::ServiceInfo> ServiceDiscovery::getAllServices(bool healthy_only) const {
        std::lock_guard<std::mutex> lock(services_mutex_);
        std::vector<ServiceInfo> result;
        
        for (const auto& [service_name, service_list] : services_) {
            for (const auto& service : service_list) {
                // 检查健康状态筛选
                if (healthy_only && !service.healthy) {
                    continue;
                }
                result.push_back(service);
            }
        }
        
        return result;
    }

    void ServiceDiscovery::healthCheckLoop() {
        LOG_INFO("健康检查线程启动");

        while (running_.load()) {
            try {
                // 收集需要更新负载均衡器的服务
                std::set<std::string> services_to_update;

                // 第一步：在锁内复制服务列表
                std::unordered_map<std::string, std::vector<ServiceInfo>> services_copy;
                {
                    std::lock_guard<std::mutex> lock(services_mutex_);
                    services_copy = services_;
                } // 锁在这里释放

                // 第二步：在锁外执行健康检查（避免阻塞其他请求）
                for (auto& [service_name, service_list] : services_copy) {
                    for (auto& service_info : service_list) {
                        bool was_healthy = service_info.healthy;
                        service_info.healthy = checkServiceHealth(service_info);

                        if (was_healthy != service_info.healthy) {
                            LOG_INFO("服务健康状态变化: " + service_name +
                                    " (" + service_info.host + ":" + std::to_string(service_info.port) + ") -> " +
                                    (service_info.healthy ? "健康" : "不健康"));

                            services_to_update.insert(service_name);
                        }
                    }
                }

                // 第三步：在锁内更新健康状态
                {
                    std::lock_guard<std::mutex> lock(services_mutex_);
                    for (const auto& [service_name, service_list] : services_copy) {
                        auto it = services_.find(service_name);
                        if (it != services_.end()) {
                            // 更新健康状态
                            for (size_t i = 0; i < service_list.size() && i < it->second.size(); ++i) {
                                it->second[i].healthy = service_list[i].healthy;
                            }
                        }
                    }
                } // 锁在这里释放

                // 第四步：在锁外更新负载均衡器
                for (const auto& service_name : services_to_update) {
                    updateLoadBalancerInstances(service_name);
                }
                
                // 清理过期服务
                cleanupExpiredServices();
                
                // 等待下次检查
                std::this_thread::sleep_for(config_.health_check_interval);
                
            } catch (const std::exception& e) {
                LOG_ERROR("健康检查循环异常: " + std::string(e.what()));
                std::this_thread::sleep_for(std::chrono::seconds(5));
            }
        }
        
        LOG_INFO("健康检查线程退出");
    }

    bool ServiceDiscovery::checkServiceHealth(ServiceInfo& service_info) {
        if (!http_client_ || service_info.health_check_endpoint.empty()) {
            LOG_DEBUG("跳过健康检查: " + service_info.service_name + " (无健康检查端点)");
            return true; // 如果没有健康检查端点，默认认为健康
        }

        try {
            std::string url = "http://" + service_info.host + ":" +
                             std::to_string(service_info.port) + service_info.health_check_endpoint;

            LOG_DEBUG("执行健康检查: " + url);

            // 发送健康检查请求
            auto response = http_client_->get(url, config_.health_check_timeout_ms);

            bool healthy = response.status_code >= 200 && response.status_code < 300;

            if (healthy) {
                LOG_DEBUG("健康检查成功: " + service_info.service_name + " (状态码: " + std::to_string(response.status_code) + ")");
            } else {
                LOG_WARNING("健康检查失败: " + service_info.service_name +
                           " (状态码: " + std::to_string(response.status_code) + ", URL: " + url + ")");
            }

            return healthy;

        } catch (const std::exception& e) {
            LOG_WARNING("健康检查异常: " + service_info.service_name +
                       " (" + service_info.host + ":" + std::to_string(service_info.port) + ") - " +
                       std::string(e.what()));
            return false;
        }
    }

    void ServiceDiscovery::updateLoadBalancerInstances(const std::string& service_name) {
        if (!load_balancer_) {
            return;
        }

        // 获取健康的服务实例（使用内部方法，需要在调用前确保已经获取锁或在锁外调用）
        std::vector<ServiceInfo> healthy_services;
        {
            std::lock_guard<std::mutex> lock(services_mutex_);
            healthy_services = getHealthyServicesInternal(service_name);
        }

        // 清除负载均衡器中的现有实例
        load_balancer_->clearServiceInstances(service_name);

        // 添加健康的实例到负载均衡器
        for (const auto& service_info : healthy_services) {
            LoadBalancer::ServiceInstance instance;
            instance.host = service_info.host;
            instance.port = service_info.port;
            instance.weight = service_info.weight;
            instance.healthy = service_info.healthy;

            load_balancer_->addServiceInstance(service_name, instance);
        }

        if (healthy_services.empty()) {
            LOG_WARNING("更新负载均衡器实例: " + service_name + " - 没有健康的服务实例！");
        } else {
            LOG_INFO("更新负载均衡器实例: " + service_name + " (健康实例数: " +
                     std::to_string(healthy_services.size()) + ")");
        }
    }

    void ServiceDiscovery::cleanupExpiredServices() {
        auto now = std::chrono::system_clock::now();
        std::set<std::string> services_to_update;

        // 在锁内清理过期服务
        {
            std::lock_guard<std::mutex> lock(services_mutex_);

            for (auto service_it = services_.begin(); service_it != services_.end();) {
                auto& service_list = service_it->second;

                // 移除过期的服务实例
                auto it = std::remove_if(service_list.begin(), service_list.end(),
                    [&](const ServiceInfo& info) {
                        auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
                            now - info.last_heartbeat);
                        return elapsed > config_.service_timeout;
                    });

                if (it != service_list.end()) {
                    size_t removed_count = std::distance(it, service_list.end());
                    service_list.erase(it, service_list.end());
                    LOG_INFO("清理过期服务实例: " + service_it->first +
                            " (移除数量: " + std::to_string(removed_count) + ")");

                    // 记录需要更新负载均衡器的服务
                    services_to_update.insert(service_it->first);
                }

                // 如果服务列表为空，删除整个服务
                if (service_list.empty()) {
                    LOG_INFO("删除空服务: " + service_it->first);
                    service_it = services_.erase(service_it);
                } else {
                    ++service_it;
                }
            }
        } // 锁在这里释放

        // 在锁外更新负载均衡器
        for (const auto& service_name : services_to_update) {
            updateLoadBalancerInstances(service_name);
        }
    }

    std::string ServiceDiscovery::generateInstanceId(const std::string& host, int port) const {
        return host + ":" + std::to_string(port);
    }

} // namespace api_gateway
} // namespace core_services
